﻿using System;
using System.Runtime.Serialization;
using System.Collections.ObjectModel;
using System.Linq;

namespace FuzzyTaskList
{
    [DataContract]
    public class FuzzyTaskItem :  BindableObject, IEquatable<FuzzyTaskItem>
    {
        #region ctors
        public FuzzyTaskItem()
        {
            _StartDate = DateTime.Now.Date;
            _Id = Guid.NewGuid().ToString();
            ComputeHistoryView();
        }
        public FuzzyTaskItem(string taskName)
            : this()
        {
            _TaskName = taskName;
        }
        public FuzzyTaskItem(string taskName, int minDays, int maxDays)
        {
            _Id = Guid.NewGuid().ToString();
            _TaskName = taskName;
            _MinDays = minDays;
            _MaxDays = maxDays;
            _StartDate = DateTime.Now.Date;
            ComputeHistoryView();
        }
        public FuzzyTaskItem(string taskName, DateTime startDate, int minDays, int maxDays)
        {
            _Id = Guid.NewGuid().ToString();
            _TaskName = taskName;
            _StartDate = startDate;
            _MinDays = minDays;
            _MaxDays = maxDays;
            ComputeHistoryView();
        }

        #endregion


        public event EventHandler<EventArgs> StartDateChanged;

        #region Properties
        private string _Id;
        [DataMember]
        public string Id
        {
            get { return _Id; }
            set
            {
                _Id = value;
                RaisePropertyChanged("Id");
            }
        }
        private string _TaskName;
        [DataMember]
        public string TaskName
        {
            get { return _TaskName; }
            set
            {
                _TaskName = value;
                RaisePropertyChanged("TaskName");
            }
        }
        public DateTime TaskSetStartDate { get; set; }


        private DateTime _StartDate;
        [DataMember]
        public DateTime StartDate
        {
            get { return _StartDate; }
            set
            {
                if (_StartDate != value)
                {
                    _StartDate = value;
                    if (StartDateChanged !=null)
                        StartDateChanged(this, new EventArgs());
                    ComputeHistoryView();
                    RaisePropertyChanged("StartDate");
                    RaisePropertyChanged("HistoryView");
                }
            }
        }

        private int _MinDays;
        [DataMember]
        public int MinDays
        {
            get { return _MinDays; }
            set
            {
                if (_MaxDays != value)
                {
                    _MinDays = value;
                    _MinDays = Math.Max(_MinDays, 1);
                    ComputeHistoryView();
                    RaisePropertyChanged("MinDays");
                    RaisePropertyChanged("HistoryView");
                }
            }
        }
        private int _MaxDays;
        [DataMember]
        public int MaxDays
        {
            get { return _MaxDays; }
            set
            {
                if (_MaxDays != value)
                {
                    _MaxDays = value;
                    _MaxDays = Math.Max(_MaxDays, 1);
                    ComputeHistoryView();
                    RaisePropertyChanged("MaxDays");
                    RaisePropertyChanged("HistoryView");
                }
            }
        }
        private bool _isActive;
        [DataMember]
        public bool IsActive
        {
            get { return _isActive; }
            set
            {
                _isActive = value;
                RaisePropertyChanged("IsActive");
            }
        }
        /// <summary>
        /// Sparse list of dates with actions
        /// </summary>
        [DataMember]
        public ObservableCollection<DateTime> History { get; private set; }

        /// <summary>
        /// Expanded list of all dates in range with action
        /// </summary>
        public ObservableCollection<ActivityItem> HistoryView { get; private set; }

        #endregion

        #region Serialization helpers
        private bool _deserializing;
        [OnDeserializing]
        private void OnDeserializing(StreamingContext c)
        {
            _deserializing = true;
        }
        [OnDeserialized]
        private void OnDeserialized(StreamingContext c)
        {
            _deserializing = false;
            TaskSetStartDate = StartDate;
            ComputeHistoryView();
        }
        #endregion

        protected internal void ComputeHistoryView()
        {
            if (_deserializing)
                return;
            if (History == null)
                History = new ObservableCollection<DateTime>();
            if (HistoryView == null)
                HistoryView = new ObservableCollection<ActivityItem>();

            //1. Make list correct size

            if (HistoryView.Count == 0)
            {
                var endDate = DateTime.Now.AddDays(Properties.Settings.Default.FutureDays).Date;
                var currentDate = StartDate;
                while (currentDate <= endDate)
                {
                    ActivityItem actitem = new ActivityItem(this, History.Contains(currentDate), currentDate);
                    HistoryView.Add(actitem);
                    currentDate = currentDate.AddDays(1);
                }
            }

            while (HistoryView[0].ActivityDate < TaskSetStartDate)
            {
                HistoryView.RemoveAt(0);
            }

            while (HistoryView[0].ActivityDate > TaskSetStartDate)
            {
                ActivityItem newActivityItem = new ActivityItem(this, false, HistoryView[0].ActivityDate.AddDays(-1));
                HistoryView.Insert(0,newActivityItem);
            }

            foreach (ActivityItem actitem in HistoryView)
            {
                actitem.RaisePropertyChanged("ActivityStatus");
            }

        }


        #region IEquatable<TaskItem> Members

        public bool Equals(FuzzyTaskItem other)
        {
            return (this.Id == other.Id);
        }

        #endregion



    }
}
